Intel VTD: Ignore USB RMRR for HVM guest
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 19 Mar 2008 10:22:49 +0000 (10:22 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 19 Mar 2008 10:22:49 +0000 (10:22 +0000)
USB controller RMRR (0xed000 - 0xeffff) conflicts with HVM guest bios
region. Setting identity mapping for it will cover the guest bios
region in p2m table. This causes system crash.

As VT-d spec says, USB controller RMRR is used in case of DMA
performed by a USB controller under BIOS SMM control for legacy
keyboard emulation. Whereas, current guest BIOS doesn't support
emulating stardand Keyboard/mouse, and it also doesn't support SMM
mode. Actually it is no chance to use USB controller RMRR now.

This patch ignores the USB controller RMRR for HVM guest.

Signed-off-by: Weidong Han <weidong.han@intel.com>
xen/drivers/passthrough/vtd/dmar.h
xen/drivers/passthrough/vtd/iommu.c
xen/drivers/passthrough/vtd/utils.c

index 46cbb19e3fae93fd1a411fa53e9133ac325f026d..040a626e03cc67329d8f6099e300042fb3c74e1e 100644 (file)
@@ -100,5 +100,6 @@ struct acpi_rmrr_unit * acpi_find_matched_rmrr_unit(struct pci_dev *dev);
 
 int vtd_hw_check(void);
 void disable_pmr(struct iommu *iommu);
+int is_usb_device(struct pci_dev *pdev);
 
 #endif // _DMAR_H_
index f1650407d5ce1809d4781d5a3f05f8906fcc2def..968e25d7f5f345cf7e5e397ae751dd3097ea1586 100644 (file)
@@ -2019,6 +2019,12 @@ int intel_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
     for_each_rmrr_device( rmrr, pdev )
         if ( pdev->bus == bus && pdev->devfn == devfn )
         {
+            /* FIXME: Because USB RMRR conflicts with guest bios region,
+             * ignore USB RMRR temporarily.
+             */
+            if ( is_usb_device(pdev) )
+                return 0;
+
             ret = iommu_prepare_rmrr_dev(d, rmrr, pdev);
             if ( ret )
             {
index b0c9d9eec51c2ec0d15731f8a57139ae4fe93143..59de4a02e8fe573bec6dc217f9da7c5775afbaf8 100644 (file)
 #define SEABURG 0x4000
 #define C_STEP  2
 
+int is_usb_device(struct pci_dev *pdev)
+{
+    u8 bus = pdev->bus;
+    u8 dev = PCI_SLOT(pdev->devfn);
+    u8 func = PCI_FUNC(pdev->devfn);
+    u16 class = read_pci_config_16(bus, dev, func, PCI_CLASS_DEVICE);
+    return (class == 0xc03);
+}
+
 int vtd_hw_check(void)
 {
     u16 vendor, device;